﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область СлужебныйПрограммныйИнтерфейс

// См. СтандартныеПодсистемыСервер.ПараметрРаботыРасширения
Функция ПараметрРаботыРасширения(ИмяПараметра, БезУчетаВерсииРасширений = Ложь, УжеИзменен = Неопределено) Экспорт
	
	ВерсияРасширений = ?(БезУчетаВерсииРасширений,
		Справочники.ВерсииРасширений.ПустаяСсылка(), ПараметрыСеанса.ВерсияРасширений);
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("ВерсияРасширений", ВерсияРасширений);
	Запрос.УстановитьПараметр("ИмяПараметра", ИмяПараметра);
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ПараметрыРаботыВерсийРасширений.ХранилищеПараметра
	|ИЗ
	|	РегистрСведений.ПараметрыРаботыВерсийРасширений КАК ПараметрыРаботыВерсийРасширений
	|ГДЕ
	|	ПараметрыРаботыВерсийРасширений.ВерсияРасширений = &ВерсияРасширений
	|	И ПараметрыРаботыВерсийРасширений.ИмяПараметра = &ИмяПараметра";
	
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);
	Выборка = Запрос.Выполнить().Выбрать();
	УстановитьПривилегированныйРежим(Ложь);
	УстановитьОтключениеБезопасногоРежима(Ложь);
	
	Если Не Выборка.Следующий() Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Попытка
		Содержимое = Выборка.ХранилищеПараметра.Получить();
	Исключение
		// При внутренней ошибке извлечения данных, обработка выполняется также
		// как в случае, когда параметр еще не заполнен.
		ИнформацияОбОшибке = ИнформацияОбОшибке();
		Комментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'При получении параметра работы версии расширений
			           |%1
			           |возникала ошибка извлечения значения из хранилища:
			           |%2'"),
			ИмяПараметра,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
		ИмяСобытия = НСтр("ru = 'Расширения конфигурации.Получение параметра работы расширений'",
			ОбщегоНазначения.КодОсновногоЯзыка());
		ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Информация,,, Комментарий);
		Возврат Неопределено;
	КонецПопытки;
	
	Если Не БезУчетаВерсииРасширений
	 Или ТипЗнч(Содержимое) <> Тип("Структура")
	 Или Содержимое.Количество() <> 5
	 Или Не Содержимое.Свойство("НомерСеансаИзменившегоПараметр")
	 Или Не Содержимое.Свойство("НачалоСеансаИзменившегоПараметр")
	 Или Не Содержимое.Свойство("КлючКомпьютераСеансаИзменившегоПараметр")
	 Или Не Содержимое.Свойство("ОперативнаяОтметкаВремениСеансаИзменившегоПараметр")
	 Или Не Содержимое.Свойство("ЗначениеПараметра") Тогда
		Возврат Содержимое;
	КонецЕсли;
	
	Если ТипЗнч(УжеИзменен) <> Тип("Булево") Тогда
		Возврат Содержимое.ЗначениеПараметра;
	КонецЕсли;
	
	ОтметкаВремени = Справочники.ВерсииРасширений.ОперативнаяОтметкаВремениСеанса();
	
	Если ТипЗнч(Содержимое.ОперативнаяОтметкаВремениСеансаИзменившегоПараметр) <> Тип("Дата")
	 Или Не ЗначениеЗаполнено(Содержимое.ОперативнаяОтметкаВремениСеансаИзменившегоПараметр) Тогда
		УжеИзменен = Истина;
	Иначе
		СвойстваСеанса = СтандартныеПодсистемыПовтИсп.СвойстваТекущегоСеанса();
		Если ОбщегоНазначения.ИнформационнаяБазаФайловая()
		   И СвойстваСеанса.КлючКомпьютера <> Содержимое.КлючКомпьютераСеансаИзменившегоПараметр Тогда
			Сдвиг = 60*60;
		Иначе
			Сдвиг = 15;
		КонецЕсли;
		Если Содержимое.ОперативнаяОтметкаВремениСеансаИзменившегоПараметр
				+ Сдвиг >= ОтметкаВремени Тогда
			УжеИзменен = Истина;
		КонецЕсли;
	КонецЕсли;
	
	Если УжеИзменен Тогда
		КонфигурацияИзменена = КонфигурацияБазыДанныхИзмененаДинамически();
		РасширенияИзменены = Справочники.ВерсииРасширений.РасширенияИзмененыДинамически();
		Если КонфигурацияИзменена Или РасширенияИзменены Тогда
			Комментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'При получении для изменения параметра работы версии расширений
				           |%1
				           |в текущем сеансе (с устаревшей версией метаданных: %2)
				           |%3
				           |обнаружено, что параметр был уже изменен в сеансе
				           |%4'"),
				ИмяПараметра,
				?(КонфигурацияИзменена И РасширенияИзменены, "Конфигурация, Расширения",
					?(КонфигурацияИзменена, "Конфигурация", "Расширения")),
				Формат(СвойстваСеанса.НачалоСеанса, "ДЛФ=DT;")
					+ " " + Формат(СвойстваСеанса.НомерСеанса, "ЧН=0; ЧГ=;")
					+ " [" + СвойстваСеанса.КлючКомпьютера + "]"
					+ " (" + Формат(ОтметкаВремени, "ДЛФ=DT;") + ")",
				Формат(Содержимое.НачалоСеансаИзменившегоПараметр, "ДЛФ=DT;")
					+ " " + Формат(Содержимое.НомерСеансаИзменившегоПараметр, "ЧН=0; ЧГ=;")
					+ " [" + Содержимое.КлючКомпьютераСеансаИзменившегоПараметр + "]"
					+ " (" + Формат(Содержимое.ОперативнаяОтметкаВремениСеансаИзменившегоПараметр, "ДЛФ=DT;") + ")");
			ИмяСобытия = НСтр("ru = 'Расширения конфигурации.Получение параметра работы расширений'",
				ОбщегоНазначения.КодОсновногоЯзыка());
			ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Информация,,, Комментарий);
		КонецЕсли;
	КонецЕсли;
	
	Возврат Содержимое.ЗначениеПараметра;
	
КонецФункции

// См. СтандартныеПодсистемыСервер.УстановитьПараметрРаботыРасширения.
Процедура УстановитьПараметрРаботыРасширения(ИмяПараметра, Значение, БезУчетаВерсииРасширений = Ложь) Экспорт
	
	ВерсияРасширений = ?(БезУчетаВерсииРасширений,
		Справочники.ВерсииРасширений.ПустаяСсылка(), ПараметрыСеанса.ВерсияРасширений);
	
	Если БезУчетаВерсииРасширений Тогда
		СвойстваСеанса = СтандартныеПодсистемыПовтИсп.СвойстваТекущегоСеанса();
		Содержимое = Новый Структура;
		Содержимое.Вставить("ЗначениеПараметра", Значение);
		Содержимое.Вставить("НомерСеансаИзменившегоПараметр",          СвойстваСеанса.НомерСеанса);
		Содержимое.Вставить("НачалоСеансаИзменившегоПараметр",         СвойстваСеанса.НачалоСеанса);
		Содержимое.Вставить("КлючКомпьютераСеансаИзменившегоПараметр", СвойстваСеанса.КлючКомпьютера);
		Содержимое.Вставить("ОперативнаяОтметкаВремениСеансаИзменившегоПараметр",
			Справочники.ВерсииРасширений.ОперативнаяОтметкаВремениСеанса());
	Иначе
		Содержимое = Значение;
	КонецЕсли;
	
	НаборЗаписей = РегистрыСведений.ПараметрыРаботыПрограммы.СлужебныйНаборЗаписей(
		РегистрыСведений.ПараметрыРаботыВерсийРасширений);
	
	НаборЗаписей.Отбор.ВерсияРасширений.Установить(ВерсияРасширений);
	НаборЗаписей.Отбор.ИмяПараметра.Установить(ИмяПараметра);
	
	НоваяЗапись = НаборЗаписей.Добавить();
	НоваяЗапись.ВерсияРасширений   = ВерсияРасширений;
	НоваяЗапись.ИмяПараметра       = ИмяПараметра;
	НоваяЗапись.ХранилищеПараметра = Новый ХранилищеЗначения(Содержимое);
	
	НаборЗаписей.Записать();
	
КонецПроцедуры

// Вызывает принудительное заполнение всех параметров работы для текущей версии расширений.
Процедура ЗаполнитьВсеПараметрыРаботыРасширений() Экспорт
	
	Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		Возврат;
	КонецЕсли;
	
	// Заполнить идентификаторы объектов метаданных расширений.
	Если ЗначениеЗаполнено(ПараметрыСеанса.ПодключенныеРасширения) Тогда
		Обновить = Справочники.ИдентификаторыОбъектовРасширений.ИдентификаторыОбъектовТекущейВерсииРасширенийЗаполнены();
		СтандартныеПодсистемыПовтИсп.ИдентификаторыОбъектовМетаданныхПроверкаИспользования(Истина, Истина);
	Иначе
		Обновить = Истина;
	КонецЕсли;
	
	Если Обновить Тогда
		Справочники.ИдентификаторыОбъектовРасширений.ОбновитьДанныеСправочника();
	КонецЕсли;
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
		МодульУправлениеДоступомСлужебный = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступомСлужебный");
		МодульУправлениеДоступомСлужебный.УстановитьЗаписьПараметровОграниченияДоступаВТекущемСеансе(Истина);
		Попытка
			ИнтеграцияПодсистемБСП.ПриЗаполненииВсехПараметровРаботыРасширений();
		Исключение
			МодульУправлениеДоступомСлужебный.УстановитьЗаписьПараметровОграниченияДоступаВТекущемСеансе(Ложь);
			ВызватьИсключение;
		КонецПопытки;
		МодульУправлениеДоступомСлужебный.УстановитьЗаписьПараметровОграниченияДоступаВТекущемСеансе(Ложь);
	Иначе
		ИнтеграцияПодсистемБСП.ПриЗаполненииВсехПараметровРаботыРасширений();
	КонецЕсли;
	
	ИмяПараметра = "СтандартныеПодсистемы.БазоваяФункциональность.ДатаПоследнегоЗаполненияВсехПараметровРаботыРасширений";
	СтандартныеПодсистемыСервер.УстановитьПараметрРаботыРасширения(ИмяПараметра, ТекущаяДатаСеанса(), Истина);
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
		МодульУправлениеДоступомСлужебный = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступомСлужебный");
		МодульУправлениеДоступомСлужебный.УстановитьОбновлениеДоступа(Истина);
	КонецЕсли;
	
КонецПроцедуры

// Возвращает дату последнего заполнения параметров работы версии расширений.
// 
// Возвращаемое значение:
//  Дата
//
Функция ДатаПоследнегоЗаполненияВсехПараметровРаботыРасширений() Экспорт
	
	ИмяПараметра = "СтандартныеПодсистемы.БазоваяФункциональность.ДатаПоследнегоЗаполненияВсехПараметровРаботыРасширений";
	ДатаОбновления = СтандартныеПодсистемыСервер.ПараметрРаботыРасширения(ИмяПараметра, Истина);
	
	Если ТипЗнч(ДатаОбновления) <> Тип("Дата") Тогда
		ДатаОбновления = '00010101';
	КонецЕсли;
	
	Возврат ДатаОбновления;
	
КонецФункции

// Вызывает принудительную очистку всех параметров работы для текущей версии расширений.
// Очищаются только регистры, справочники не изменяются. Вызывается, чтобы вызвать
// перезаполнение параметров работы расширений, например, при использовании параметра
// запуска ЗапуститьОбновлениеИнформационнойБазы.
// 
// Общий регистр ПараметрыРаботыВерсийРасширений очищается автоматически. Если используются
// собственные регистры сведений, которых хранят версии кэшей объектов метаданных расширений,
// тогда требуется подключиться к событию ПриОчисткеВсехПараметровРаботыРасширений
// общего модуля ИнтеграцияПодсистемБСП.
//
Процедура ОчиститьВсеПараметрыРаботыРасширений() Экспорт
	
	Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		Возврат;
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	
	НачатьТранзакцию();
	Попытка
		НаборЗаписей = РегистрыСведений.ПараметрыРаботыПрограммы.СлужебныйНаборЗаписей(
			РегистрыСведений.ИдентификаторыОбъектовВерсийРасширений);
		НаборЗаписей.Отбор.ВерсияРасширений.Установить(ПараметрыСеанса.ВерсияРасширений);
		НаборЗаписей.Записать();
		
		НаборЗаписей = РегистрыСведений.ПараметрыРаботыПрограммы.СлужебныйНаборЗаписей(
			РегистрыСведений.ПараметрыРаботыВерсийРасширений);
		НаборЗаписей.Отбор.ВерсияРасширений.Установить(ПараметрыСеанса.ВерсияРасширений);
		НаборЗаписей.Записать();
		
		ИнтеграцияПодсистемБСП.ПриОчисткеВсехПараметровРаботыРасширений();
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
	ОбновитьПовторноИспользуемыеЗначения();
	
КонецПроцедуры

// Для общей формы Расширения.
Процедура ЗаполнитьВсеПараметрыРаботыРасширенийФоновоеЗадание(Параметры) Экспорт
	
	ТекстОшибки = "";
	НеподключенныеРасширения = "";
	
	Если Параметры.ИмяКонфигурации    <> Метаданные.Имя
	 Или Параметры.ВерсияКонфигурации <> Метаданные.Версия Тогда
		ТекстОшибки =
			НСтр("ru = 'Не удалось обновить все параметры работы расширений, так как
			           |изменилось имя или версия конфигурации - требуется перезапуск сеанса.'");
	КонецЕсли;
	
	УстановленныеРасширения = Справочники.ВерсииРасширений.УстановленныеРасширения();
	
	Если Параметры.УстановленныеРасширения.Основные    <> УстановленныеРасширения.Основные
	 Или Параметры.УстановленныеРасширения.Исправления <> УстановленныеРасширения.Исправления Тогда
		ТекстОшибки =
			НСтр("ru = 'Не удалось обновить все параметры работы расширений, так как
			           |повторно изменился состав расширений до запуска задания обновления.
			           |Повторите операцию.'");
	КонецЕсли;
	
	Если ТипЗнч(Параметры.ПроверяемыеРасширения) = Тип("Соответствие") Тогда
		Расширения = РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные); // Массив из РасширениеКонфигурации -
		ПодключенныеРасширения = Новый Соответствие;
		Для Каждого Расширение Из Расширения Цикл
			ПодключенныеРасширения[Расширение.Имя] = Истина;
		КонецЦикла;
		Для Каждого ПроверяемоеРасширение Из Параметры.ПроверяемыеРасширения Цикл
			Если ПодключенныеРасширения[ПроверяемоеРасширение.Ключ] = Неопределено Тогда
				НеподключенныеРасширения = НеподключенныеРасширения
					 + ?(НеподключенныеРасширения = "", "", ", ") + ПроверяемоеРасширение.Значение;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(ТекстОшибки) Тогда
		Попытка
			ЗаполнитьВсеПараметрыРаботыРасширений();
		Исключение
			ИнформацияОбОшибке = ИнформацияОбОшибке();
			ТекстОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
		КонецПопытки;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(ТекстОшибки) Тогда
		ОтметитьЗаполнениеПараметровРаботыРасширений();
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Параметры.ТекстДляАсинхронногоВызова) Тогда
		Если ЗначениеЗаполнено(ТекстОшибки) Тогда
			ТекстОшибки = Параметры.ТекстДляАсинхронногоВызова + ":" + Символы.ПС + ТекстОшибки;
			ВызватьИсключение ТекстОшибки;
		Иначе
			Возврат;
		КонецЕсли;
	КонецЕсли;
	
	Результат = Новый Структура;
	Результат.Вставить("ТекстОшибки",              ТекстОшибки);
	Результат.Вставить("НеподключенныеРасширения", НеподключенныеРасширения);
	
	ПоместитьВоВременноеХранилище(Результат, Параметры.АдресРезультата);
	
КонецПроцедуры

Процедура ОбновитьПараметрыРаботыРасширений(ПроверяемыеРасширения = Неопределено, НеподключенныеРасширения = "", ТекстДляАсинхронногоВызова = "") Экспорт
	
	Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		Возврат;
	КонецЕсли;
	
	ПараметрыВыполнения = Новый Структура;
	ПараметрыВыполнения.Вставить("ИмяКонфигурации",         Метаданные.Имя);
	ПараметрыВыполнения.Вставить("ВерсияКонфигурации",      Метаданные.Версия);
	ПараметрыВыполнения.Вставить("УстановленныеРасширения", Справочники.ВерсииРасширений.УстановленныеРасширения());
	ПараметрыВыполнения.Вставить("ПроверяемыеРасширения",   ПроверяемыеРасширения);
	ПараметрыВыполнения.Вставить("АдресРезультата",         ПоместитьВоВременноеХранилище(Неопределено));
	ПараметрыВыполнения.Вставить("ТекстДляАсинхронногоВызова", ТекстДляАсинхронногоВызова);
	ПараметрыПроцедуры = Новый Массив;
	ПараметрыПроцедуры.Добавить(ПараметрыВыполнения);
	
	ТекущийСеанс = ПолучитьТекущийСеансИнформационнойБазы();
	НаименованиеЗадания =
		НСтр("ru = 'Общая форма Расширения: Заполнение параметров работы расширений'",
			ОбщегоНазначения.КодОсновногоЯзыка())
		 + " (" + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'из сеанса %1 от %2'", ОбщегоНазначения.КодОсновногоЯзыка()),
			Формат(ТекущийСеанс.НомерСеанса, "ЧГ="),
			Формат(ТекущийСеанс.НачалоСеанса, "ДЛФ=DT")) + ")";
	
	ФоновоеЗадание = РасширенияКонфигурации.ВыполнитьФоновоеЗаданиеСРасширениямиБазыДанных(
		"СтандартныеПодсистемыСервер.ЗаполнитьВсеПараметрыРаботыРасширенийФоновоеЗадание",
		ПараметрыПроцедуры, , НаименованиеЗадания);
	
	Если ЗначениеЗаполнено(ТекстДляАсинхронногоВызова) Тогда
		Возврат;
	КонецЕсли;
	ФоновоеЗадание.ОжидатьЗавершенияВыполнения();
	Отбор = Новый Структура("УникальныйИдентификатор", ФоновоеЗадание.УникальныйИдентификатор);
	ФоновоеЗадание = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор)[0];
	Если ФоновоеЗадание.ИнформацияОбОшибке <> Неопределено Тогда
		ТекстОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ФоновоеЗадание.ИнформацияОбОшибке);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Результат = ПолучитьИзВременногоХранилища(ПараметрыВыполнения.АдресРезультата);
	Если ТипЗнч(Результат) <> Тип("Структура") Тогда
		ТекстОшибки = НСтр("ru = 'Фоновое задание подготовки расширений не вернуло результат.'");
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Результат.ТекстОшибки) Тогда
		ВызватьИсключение Результат.ТекстОшибки;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Результат.НеподключенныеРасширения) Тогда
		НеподключенныеРасширения = Результат.НеподключенныеРасширения;
	КонецЕсли;
	
КонецПроцедуры

// Для процедуры ОбработатьПараметрыКлиентаНаСервере общего модуля СтандартныеПодсистемыВызовСервера.
Процедура ПриПервомСерверномВызове() Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	
	Если ТекущийРежимЗапуска() = Неопределено
	 Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных()
	 Или Не ТребуетсяВключитьЗаполнениеПараметровРаботыРасширений()
	 Или РегистрыСведений.ПараметрыРаботыПрограммы.НеобходимоОбновление()
	 Или Не ОбщегоНазначения.РазделениеВключено()
	   И ПланыОбмена.ГлавныйУзел() = Неопределено
	   И ЗначениеЗаполнено(Константы.ГлавныйУзел.Получить()) Тогда
		Возврат;
	КонецЕсли;
	
	ВключитьЗаполнениеПараметровРаботыРасширений(ОбщегоНазначения.РежимОтладки()
		Или Не ОбщегоНазначения.ИнформационнаяБазаФайловая()
		  И ОбщегоНазначения.РазделениеВключено());
	
КонецПроцедуры

// Для процедуры ПриНачалеВыполненияРегламентногоЗадания общего модуля ОбщегоНазначения.
Процедура ПриУспешномНачалеВыполненияРегламентногоЗадания() Экспорт
	
	Если ОбщегоНазначения.РазделениеВключено() Тогда
		Возврат;
	КонецЕсли;
	
	ТекущийСеанс = ПолучитьТекущийСеансИнформационнойБазы();
	Если ТекущийСеанс.ИмяПриложения <> "BackgroundJob" Тогда
		Возврат;
	КонецЕсли;
	
	Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных()
	 Или Не ТребуетсяВключитьЗаполнениеПараметровРаботыРасширений() Тогда
		Возврат;
	КонецЕсли;
	
	ТекущееФоновоеЗадание = ТекущийСеанс.ПолучитьФоновоеЗадание();
	МетаданныеЗадания = Метаданные.РегламентныеЗадания.ЗаполнениеПараметровРаботыРасширений;
	Запустить = ТекущееФоновоеЗадание <> Неопределено
		И ТекущееФоновоеЗадание.ИмяМетода <> МетаданныеЗадания.ИмяМетода
		И (Не ОбщегоНазначения.РазделениеВключено()
		   Или ОбластьДанныхАктивноИспользуется());
	
	ВключитьЗаполнениеПараметровРаботыРасширений(Запустить);
	
КонецПроцедуры

// Только для вызова из СтандартныеПодсистемыСервер.ЗаполнениеПараметровРаботыРасширений.
// 
// Обработчик регламентного задания ЗаполнениеПараметровРаботыРасширений.
// 
Процедура ЗаполнитьВсеПараметрыРаботыПоследнейВерсииРасширений() Экспорт
	
	Если ТранзакцияАктивна() Тогда
		Возврат;
	КонецЕсли;
	
	ТекущийСеанс = ПолучитьТекущийСеансИнформационнойБазы();
	Если ТекущийСеанс.ИмяПриложения <> "BackgroundJob" Тогда
		Возврат;
	КонецЕсли;
	ТекущееФоновоеЗадание = ТекущийСеанс.ПолучитьФоновоеЗадание();
	Если ТекущееФоновоеЗадание = Неопределено Тогда
		Возврат;
	КонецЕсли;
	ИдентификаторТекущегоЗадания = ТекущееФоновоеЗадание.УникальныйИдентификатор;
	
	// Регистрация текущего фонового задания как исполняющего, либо завершение, если существует.
	ИмяПараметра = "СтандартныеПодсистемы.БазоваяФункциональность.ЗаданиеЗаполненияПараметровРаботыРасширений";
	ИдентификаторЗадания = СтандартныеПодсистемыСервер.ПараметрРаботыРасширения(ИмяПараметра, Истина);
	ИсполняющееФоновоеЗадание = Неопределено;
	ЗаполнитьАктивноеФоновоеЗадание(ИсполняющееФоновоеЗадание, ИдентификаторЗадания);
	Если ИсполняющееФоновоеЗадание <> Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ПараметрыРаботыВерсийРасширений");
	ЭлементБлокировки.УстановитьЗначение("ВерсияРасширений", Справочники.ВерсииРасширений.ПустаяСсылка());
	ЭлементБлокировки.УстановитьЗначение("ИмяПараметра", ИмяПараметра);
	БлокировкаУстановлена = Ложь;
	
	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		БлокировкаУстановлена = Истина;
		ИдентификаторЗадания = СтандартныеПодсистемыСервер.ПараметрРаботыРасширения(ИмяПараметра, Истина);
		ЗаполнитьАктивноеФоновоеЗадание(ИсполняющееФоновоеЗадание, ИдентификаторЗадания);
		Если ИсполняющееФоновоеЗадание = Неопределено Тогда
			СтандартныеПодсистемыСервер.УстановитьПараметрРаботыРасширения(ИмяПараметра,
				ИдентификаторТекущегоЗадания, Истина);
		КонецЕсли;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		Если БлокировкаУстановлена Тогда
			ВызватьИсключение;
		КонецЕсли;
		ЗапуститьЗаполнениеПараметровРаботыРасширений(
			НСтр("ru = 'Перезапуск из-за неудачной попытки блокировки параметра'"));
		Возврат;
	КонецПопытки;
	
	Если ИсполняющееФоновоеЗадание <> Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	// Перезапуск, если метаданные уже не актуальны.
	ВерсияРасширений = ПараметрыСеанса.ВерсияРасширений;
	ВерсияПриЗапуске = Справочники.ВерсииРасширений.ПоследняяВерсияРасширений();
	
	Если ВерсияПриЗапуске.ВерсияРасширений <> ВерсияРасширений
	 Или КонфигурацияБазыДанныхИзмененаДинамически()
	 Или Справочники.ВерсииРасширений.РасширенияИзмененыДинамически() Тогда
		
		СтандартныеПодсистемыСервер.УстановитьПараметрРаботыРасширения(ИмяПараметра, Неопределено, Истина);
		ЗапуститьЗаполнениеПараметровРаботыРасширений(
			НСтр("ru = 'Перезапуск из-за изменения метаданных расширений или
			           |конфигурации после запуска до начала обновления'"));
		Возврат;
	КонецЕсли;
	
	// Заполнение всех параметров работы текущей версии расширений.
	НомерПопытки = 1;
	КоличествоПопыток = 3;
	ПредыдущаяОшибка = "";
	Пока Истина Цикл
		Попытка
			ЗаполнитьВсеПараметрыРаботыРасширений();
		Исключение
			ИнформацияОбОшибке = ИнформацияОбОшибке();
			ТребуетсяПерезапускСеанса = СтандартныеПодсистемыСервер.ТребуетсяПерезапускСеанса();
			Если Не ТребуетсяПерезапускСеанса
			 Или Не СтандартныеПодсистемыСервер.ЭтоОшибкаТребованияПерезапускаСеанса(ИнформацияОбОшибке) Тогда
				ТекущаяОшибка = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
				Если ПредыдущаяОшибка = ТекущаяОшибка Тогда
					ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
						НСтр("ru = 'При попытке заполнения %1 из %2 повторилась ошибка предыдущей попытки.'",
							ОбщегоНазначения.КодОсновногоЯзыка()),
						Формат(НомерПопытки, "ЧГ="),
						Формат(КоличествоПопыток, "ЧГ="));
				Иначе
					ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
						НСтр("ru = 'При попытке заполнения %1 из %2 возникла ошибка:
						           |%3'",
							ОбщегоНазначения.КодОсновногоЯзыка()),
						Формат(НомерПопытки, "ЧГ="),
						Формат(КоличествоПопыток, "ЧГ="),
						ТекущаяОшибка);
					ДобавитьДополнительныеСведения(ТекстОшибки);
				КонецЕсли;
				ПредыдущаяОшибка = ТекущаяОшибка;
				ЗаписьЖурналаРегистрации(ИмяСобытияЗаполненияПараметров(),
					УровеньЖурналаРегистрации.Ошибка,,, ТекстОшибки);
			КонецЕсли;
			Если ТребуетсяПерезапускСеанса Тогда
				СтандартныеПодсистемыСервер.УстановитьПараметрРаботыРасширения(ИмяПараметра, Неопределено, Истина);
				ЗапуститьЗаполнениеПараметровРаботыРасширений(
					НСтр("ru = 'Перезапуск из-за изменения метаданных или
					           |расширений в процессе заполнения параметров'"));
				Возврат;
			КонецЕсли;
			НомерПопытки = НомерПопытки + 1;
			Если НомерПопытки <= КоличествоПопыток Тогда
				Продолжить;
			КонецЕсли;
		КонецПопытки;
		Прервать;
	КонецЦикла;
	
	Если Не ЗначениеЗаполнено(ПредыдущаяОшибка) Тогда
		Комментарий = НСтр("ru = 'Заполнение выполнено успешно.'",
			ОбщегоНазначения.КодОсновногоЯзыка());
		ДобавитьДополнительныеСведения(Комментарий);
		ЗаписьЖурналаРегистрации(ИмяСобытияЗаполненияПараметров(),
			УровеньЖурналаРегистрации.Информация,,, Комментарий);
	КонецЕсли;
	
	Перезапустить = Ложь;
	ОтключитьЗаполнениеПараметровРаботыРасширений(ВерсияПриЗапуске, Перезапустить);
	
	Если Перезапустить Тогда
		СтандартныеПодсистемыСервер.УстановитьПараметрРаботыРасширения(ИмяПараметра, Неопределено, Истина);
		ЗапуститьЗаполнениеПараметровРаботыРасширений(
			НСтр("ru = 'Перезапуск из-за изменения метаданных или
			           |расширений после заполнения параметров'"));
	КонецЕсли;
	
КонецПроцедуры

// Для процедуры процедуры ОбновитьПараметрыРаботыВерсийРасширенийСУчетомРежимаВыполнения
// модуля менеджера регистра сведений ПараметрыРаботыПрограммы и
// процедуры ЗаполнитьВсеПараметрыРаботыРасширенийФоновоеЗадание этого модуля.
//
Процедура ОтметитьЗаполнениеПараметровРаботыРасширений() Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	
	Справочники.ВерсииРасширений.ЗарегистрироватьИспользованиеВерсииРасширений();
	ВерсияРасширений = ПараметрыСеанса.ВерсияРасширений;
	ПоследняяВерсия = Справочники.ВерсииРасширений.ПоследняяВерсияРасширений();
	Если ПоследняяВерсия.ВерсияРасширений = ВерсияРасширений Тогда
		ОтключитьЗаполнениеПараметровРаботыРасширений(ПоследняяВерсия);
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Ложь);
	
КонецПроцедуры

Функция ИмяСобытияЗаполненияПараметров() Экспорт
	
	Возврат НСтр("ru = 'Расширения конфигурации.Заполнение параметров работы расширений'",
		ОбщегоНазначения.КодОсновногоЯзыка());
	
КонецФункции

Функция НаименованиеЗаданияЗаполненияПараметров() Экспорт
	
	Возврат НСтр("ru = 'Заполнение параметров работы расширений'",
		ОбщегоНазначения.КодОсновногоЯзыка());
	
КонецФункции

Процедура ЗаблокироватьДляИзмененияВФайловойИБ() Экспорт
	
	Если ТранзакцияАктивна() И ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда
		Блокировка = Новый БлокировкаДанных;
		Блокировка.Добавить("РегистрСведений.ПараметрыРаботыВерсийРасширений");
		// АПК:1320-выкл - №783.1.3 Допустимо вызывать блокировку во внешней транзакции для файловой ИБ.
		// Требуется для предотвращения взаимоблокировки из-за автоматической установки
		// разделяемой блокировки в файловой ИБ на таблицу при чтении запросом в транзакции.
		Блокировка.Заблокировать();
		// АПК:1320-вкл.
	КонецЕсли;
	
КонецПроцедуры

#Область ИнструментРазработчикаОбновлениеВспомогательныхДанных

// Параметры:
//  Обновлять - Булево - начальное значение Ложь
//
// Возвращаемое значение:
//  Структура:
//   * БазоваяФункциональность - Структура:
//      ** ИдентификаторыОбъектовРасширений - см. СвойстваПараметраОбновления
//   * ПодключаемыеКоманды - Структура:
//      ** ПодключаемыеКомандыРасширений - см. СвойстваПараметраОбновления
//   * Пользователи - Структура:
//      ** СоставыГруппПользователей - см. СвойстваПараметраОбновления
//   * УправлениеДоступом - Структура:
//      ** ПоставляемыеПрофилиГруппДоступа     - см. СвойстваПараметраОбновления
//      ** НепоставляемыеПрофилиГруппДоступа   - см. СвойстваПараметраОбновления
//      ** РолиПользователейИнформационнойБазы - см. СвойстваПараметраОбновления
//      ** ПараметрыОграниченияДоступа         - см. СвойстваПараметраОбновления
//      ** ТаблицыГруппДоступа                 - см. СвойстваПараметраОбновления
//      ** ЗначенияГруппДоступа                - см. СвойстваПараметраОбновления
//      ** НаследованиеНастроекПравОбъектов    - см. СвойстваПараметраОбновления
//      ** НастройкиПравОбъектов               - см. СвойстваПараметраОбновления
//      ** ГруппыЗначенийДоступа               - см. СвойстваПараметраОбновления
//      ** НаборыЗначенийДоступа               - см. СвойстваПараметраОбновления
//   * ВариантыОтчетов - Структура:
//      ** ОтчетыКонфигурации              - см. СвойстваПараметраОбновления
//      ** ИндексПоискаОтчетовКонфигурации - см. СвойстваПараметраОбновления
//      ** ОтчетыРасширений                - см. СвойстваПараметраОбновления
//      ** ИндексПоискаОтчетовРасширений   - см. СвойстваПараметраОбновления
//   * КонтрольВеденияУчета - Структура:
//      ** ПравилаПроверкиУчета - см. СвойстваПараметраОбновления
//
Функция ПараметрыОбновления(Обновлять = Ложь) Экспорт
	
	Параметры = Новый Структура;
	
	// СтандартныеПодсистемы БазоваяФункциональность
	ПараметрыПодсистемы = Новый Структура;
	ПараметрыПодсистемы.Вставить("ИдентификаторыОбъектовРасширений", НовыеСвойстваПараметраОбновления(Обновлять));
	Параметры.Вставить("БазоваяФункциональность", ПараметрыПодсистемы);
	
	// СтандартныеПодсистемы ПодключаемыеКоманды
	ПараметрыПодсистемы = Новый Структура;
	ПараметрыПодсистемы.Вставить("ПодключаемыеКомандыРасширений", НовыеСвойстваПараметраОбновления(Обновлять));
	Параметры.Вставить("ПодключаемыеКоманды", ПараметрыПодсистемы);
	
	// СтандартныеПодсистемы Пользователи
	ПараметрыПодсистемы = Новый Структура;
	ПараметрыПодсистемы.Вставить("СоставыГруппПользователей", НовыеСвойстваПараметраОбновления(Обновлять));
	Параметры.Вставить("Пользователи", ПараметрыПодсистемы);
	
	// СтандартныеПодсистемы УправлениеДоступом
	ПараметрыПодсистемы.Вставить("ПоставляемыеПрофилиГруппДоступа",     НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("НепоставляемыеПрофилиГруппДоступа",   НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("РолиПользователейИнформационнойБазы", НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("ПараметрыОграниченияДоступа",         НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("ТаблицыГруппДоступа",                 НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("ЗначенияГруппДоступа",                НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("НаследованиеНастроекПравОбъектов",    НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("НастройкиПравОбъектов",               НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("ГруппыЗначенийДоступа",               НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("НаборыЗначенийДоступа",               НовыеСвойстваПараметраОбновления(Обновлять));
	Параметры.Вставить("УправлениеДоступом", ПараметрыПодсистемы);
	
	// СтандартныеПодсистемы ВариантыОтчетов
	ПараметрыПодсистемы.Вставить("ОтчетыКонфигурации",              НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("ИндексПоискаОтчетовКонфигурации", НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("ОтчетыРасширений",                НовыеСвойстваПараметраОбновления(Обновлять));
	ПараметрыПодсистемы.Вставить("ИндексПоискаОтчетовРасширений",   НовыеСвойстваПараметраОбновления(Обновлять));
	Параметры.Вставить("ВариантыОтчетов", ПараметрыПодсистемы);
	
	// СтандартныеПодсистемы КонтрольВеденияУчета
	ПараметрыПодсистемы.Вставить("ПравилаПроверкиУчета", НовыеСвойстваПараметраОбновления(Обновлять));
	Параметры.Вставить("КонтрольВеденияУчета", ПараметрыПодсистемы);
	
	Возврат Параметры;
	
КонецФункции

// Параметры:
//  Параметры - см. ПараметрыОбновления
//  ИдентификаторФормы - УникальныйИдентификатор
//
Процедура ВыполнитьОбновлениеРазделенныхДанныхВФоне(Параметры, ИдентификаторФормы) Экспорт
	
	ПараметрыОперации = ДлительныеОперации.ПараметрыВыполненияВФоне(ИдентификаторФормы);
	ПараметрыОперации.НаименованиеФоновогоЗадания = НСтр("ru = 'Обновление разделенных вспомогательных данных'");
	ПараметрыОперации.СРасширениямиБазыДанных = Истина;
	ПараметрыОперации.ОжидатьЗавершение = Неопределено;
	
	ИмяПроцедуры = "РегистрыСведений.ПараметрыРаботыВерсийРасширений.ОбработчикДлительнойОперацииВыполнитьОбновлениеРазделенныхДанных";
	ДлительнаяОперация = ДлительныеОперации.ВыполнитьВФоне(ИмяПроцедуры, Параметры, ПараметрыОперации);
	
	Если ДлительнаяОперация.Статус <> "Выполнено" Тогда
		Если ДлительнаяОперация.Статус = "Ошибка" Тогда
			ТекстОшибки = ДлительнаяОперация.ПодробноеПредставлениеОшибки;
		ИначеЕсли ДлительнаяОперация.Статус = "Отменено" Тогда
			ТекстОшибки = НСтр("ru = 'Фоновое задание отменено'");
		Иначе
			ТекстОшибки = НСтр("ru = 'Ошибка выполнения фонового задания'");
		КонецЕсли;
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Результат = ПолучитьИзВременногоХранилища(ДлительнаяОперация.АдресРезультата);
	Если ТипЗнч(Результат) <> Тип("Структура") Тогда
		ТекстОшибки = НСтр("ru = 'Фоновое задание не вернуло результат'");
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Параметры = Результат;
	
КонецПроцедуры

// Параметры:
//  Параметры - см. ПараметрыОбновления
//  АдресРезультата - Строка
//
Процедура ОбработчикДлительнойОперацииВыполнитьОбновлениеРазделенныхДанных(Параметры, АдресРезультата) Экспорт
	
	Если ОбщегоНазначения.РазделениеВключено()
	   И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		ТекстОшибки =
			НСтр("ru = 'Не удалось обновить параметры работы расширений по причине:
			           |Обновление невозможно выполнить в неразделенном режиме.'");
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	СтандартныеПодсистемыСервер.ПроверитьДинамическоеОбновлениеВерсииПрограммы();
	Если Справочники.ВерсииРасширений.РасширенияИзмененыДинамически() Тогда
		СтандартныеПодсистемыСервер.ПотребоватьПерезапускСеансаПоПричинеДинамическогоОбновленияРасширенийПрограммы();
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	
	// СтандартныеПодсистемы БазоваяФункциональность
	Если Параметры.БазоваяФункциональность.ИдентификаторыОбъектовРасширений.Обновлять Тогда
		Справочники.ИдентификаторыОбъектовРасширений.ОбновитьДанныеСправочника(
			Параметры.БазоваяФункциональность.ИдентификаторыОбъектовРасширений.ЕстьИзменения);
	КонецЕсли;
	
	// СтандартныеПодсистемы ПодключаемыеКоманды
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ПодключаемыеКоманды") Тогда
		МодульПодключаемыеКоманды = ОбщегоНазначения.ОбщийМодуль("ПодключаемыеКоманды");
		Если Параметры.ПодключаемыеКоманды.ПодключаемыеКомандыРасширений.Обновлять Тогда
			Параметры.ПодключаемыеКоманды.ПодключаемыеКомандыРасширений.ЕстьИзменения =
				МодульПодключаемыеКоманды.ПриЗаполненииВсехПараметровРаботыРасширений().ЕстьИзменения;
		КонецЕсли;
	КонецЕсли;
	
	// СтандартныеПодсистемы Пользователи
	Если Параметры.Пользователи.СоставыГруппПользователей.Обновлять Тогда
		РегистрыСведений.СоставыГруппПользователей.ОбновитьДанныеРегистра(
			Параметры.Пользователи.СоставыГруппПользователей.ЕстьИзменения);
	КонецЕсли;
	
	// СтандартныеПодсистемы УправлениеДоступом
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
		Если Параметры.УправлениеДоступом.ПоставляемыеПрофилиГруппДоступа.Обновлять Тогда
			МодульГруппыДоступа = ОбщегоНазначения.ОбщийМодуль("Справочники.ГруппыДоступа");
			МодульГруппыДоступа.ПометитьНаУдалениеГруппыДоступаПомеченныхПрофилей(
				Параметры.УправлениеДоступом.ПоставляемыеПрофилиГруппДоступа.ЕстьИзменения);
			МодульПрофилиГруппДоступа = ОбщегоНазначения.ОбщийМодуль("Справочники.ПрофилиГруппДоступа");
			МодульПрофилиГруппДоступа.ОбновитьПоставляемыеПрофили(
				Параметры.УправлениеДоступом.ПоставляемыеПрофилиГруппДоступа.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.НепоставляемыеПрофилиГруппДоступа.Обновлять Тогда
			МодульПрофилиГруппДоступа = ОбщегоНазначения.ОбщийМодуль("Справочники.ПрофилиГруппДоступа");
			МодульПрофилиГруппДоступа.ОбновитьНепоставляемыеПрофили(
				Параметры.УправлениеДоступом.НепоставляемыеПрофилиГруппДоступа.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.РолиПользователейИнформационнойБазы.Обновлять Тогда
			МодульУправлениеДоступомСлужебный = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступомСлужебный");
			МодульУправлениеДоступомСлужебный.ОбновитьРолиПользователей(,,
				Параметры.УправлениеДоступом.РолиПользователейИнформационнойБазы.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.ПараметрыОграниченияДоступа.Обновлять Тогда
			МодульПараметрыОграниченияДоступа = ОбщегоНазначения.ОбщийМодуль(
				"РегистрыСведений.ПараметрыОграниченияДоступа");
			МодульПараметрыОграниченияДоступа.ОбновитьДанныеРегистра(
				Параметры.УправлениеДоступом.ПараметрыОграниченияДоступа.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.ТаблицыГруппДоступа.Обновлять Тогда
			МодульТаблицыГруппДоступа = ОбщегоНазначения.ОбщийМодуль(
				"РегистрыСведений.ТаблицыГруппДоступа");
			МодульТаблицыГруппДоступа.ОбновитьДанныеРегистра(,,
				Параметры.УправлениеДоступом.ТаблицыГруппДоступа.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.ЗначенияГруппДоступа.Обновлять Тогда
			МодульЗначенияГруппДоступа = ОбщегоНазначения.ОбщийМодуль(
				"РегистрыСведений.ЗначенияГруппДоступа");
			МодульЗначенияГруппДоступа.ОбновитьДанныеРегистра(,
				Параметры.УправлениеДоступом.ЗначенияГруппДоступа.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.НаследованиеНастроекПравОбъектов.Обновлять Тогда
			МодульНаследованиеНастроекПравОбъектов = ОбщегоНазначения.ОбщийМодуль(
				"РегистрыСведений.НаследованиеНастроекПравОбъектов");
			МодульНаследованиеНастроекПравОбъектов.ОбновитьДанныеРегистра(,
				Параметры.УправлениеДоступом.НаследованиеНастроекПравОбъектов.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.НастройкиПравОбъектов.Обновлять Тогда
			МодульНастройкиПравОбъектов = ОбщегоНазначения.ОбщийМодуль(
				"РегистрыСведений.НастройкиПравОбъектов");
			МодульНастройкиПравОбъектов.ОбновитьВспомогательныеДанныеРегистра(
				Параметры.УправлениеДоступом.НастройкиПравОбъектов.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.ГруппыЗначенийДоступа.Обновлять Тогда
			МодульГруппыЗначенийДоступа = ОбщегоНазначения.ОбщийМодуль(
				"РегистрыСведений.ГруппыЗначенийДоступа");
			МодульГруппыЗначенийДоступа.ОбновитьДанныеРегистра(
				Параметры.УправлениеДоступом.ГруппыЗначенийДоступа.ЕстьИзменения);
		КонецЕсли;
		Если Параметры.УправлениеДоступом.НаборыЗначенийДоступа.Обновлять Тогда
			МодульНаборыЗначенийДоступа = ОбщегоНазначения.ОбщийМодуль(
				"РегистрыСведений.НаборыЗначенийДоступа");
			МодульНаборыЗначенийДоступа.ОбновитьДанныеРегистра(
				Параметры.УправлениеДоступом.НаборыЗначенийДоступа.ЕстьИзменения);
		КонецЕсли;
	КонецЕсли;
	
	// СтандартныеПодсистемы ВариантыОтчетов
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ВариантыОтчетов") Тогда
		МодульВариантыОтчетов = ОбщегоНазначения.ОбщийМодуль("ВариантыОтчетов");
		
		Настройки = МодульВариантыОтчетов.ПараметрыОбновленияНастроек();
		Настройки.ОбщиеДанные = Ложь;
		Настройки.РазделенныеДанные = Истина;
		Настройки.Конфигурация = Истина;
		Настройки.Расширения = Ложь;
		Если Параметры.ВариантыОтчетов.ОтчетыКонфигурации.Обновлять Тогда
			Настройки.Оперативное = Истина;
			Настройки.Отложенное = Ложь;
			Параметры.ВариантыОтчетов.ОтчетыКонфигурации.ЕстьИзменения =
				МодульВариантыОтчетов.Обновить(Настройки).ЕстьИзменения;
		КонецЕсли;
		Если Параметры.ВариантыОтчетов.ИндексПоискаОтчетовКонфигурации.Обновлять Тогда
			Настройки.Оперативное = Ложь;
			Настройки.Отложенное = Истина;
			Настройки.ИндексироватьСхему = Истина;
			Параметры.ВариантыОтчетов.ИндексПоискаОтчетовКонфигурации.ЕстьИзменения =
				МодульВариантыОтчетов.Обновить(Настройки).ЕстьИзменения;
		КонецЕсли;
		
		Настройки = МодульВариантыОтчетов.ПараметрыОбновленияНастроек();
		Настройки.ОбщиеДанные = Истина; // Предопределенные.
		Настройки.РазделенныеДанные = Истина;
		Настройки.Конфигурация = Ложь;
		Настройки.Расширения = Истина;
		Если Параметры.ВариантыОтчетов.ОтчетыРасширений.Обновлять Тогда
			Настройки.Оперативное = Истина;
			Настройки.Отложенное = Ложь;
			Параметры.ВариантыОтчетов.ОтчетыРасширений.ЕстьИзменения =
				МодульВариантыОтчетов.Обновить(Настройки).ЕстьИзменения;
		КонецЕсли;
		Если Параметры.ВариантыОтчетов.ИндексПоискаОтчетовРасширений.Обновлять Тогда
			Настройки.Оперативное = Ложь;
			Настройки.Отложенное = Истина;
			Настройки.ИндексироватьСхему = Истина;
			Параметры.ВариантыОтчетов.ИндексПоискаОтчетовРасширений.ЕстьИзменения =
				МодульВариантыОтчетов.Обновить(Настройки).ЕстьИзменения;
		КонецЕсли;
	КонецЕсли;
	
	// СтандартныеПодсистемы КонтрольВеденияУчета
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
		МодульКонтрольВеденияУчетаСлужебный = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчетаСлужебный");
		Если Параметры.КонтрольВеденияУчета.ПравилаПроверкиУчета.Обновлять Тогда
			МодульКонтрольВеденияУчетаСлужебный.ОбновитьВспомогательныеДанныеПоИзменениямКонфигурации();
			Параметры.КонтрольВеденияУчета.ПравилаПроверкиУчета.ЕстьИзменения = Истина;
		КонецЕсли;
	КонецЕсли;
	
	ПоместитьВоВременноеХранилище(Параметры, АдресРезультата);
	
КонецПроцедуры

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Для процедур ПриПервомСерверномВызове, ПриУспешномНачалеВыполненияРегламентногоЗадания и
// ОтключитьЗаполнениеПараметровРаботыРасширений.
//
Функция ТребуетсяВключитьЗаполнениеПараметровРаботыРасширений()
	
	ПоследняяВерсияРасширений = Справочники.ВерсииРасширений.ПоследняяВерсияРасширений();
	
	ИмяПараметра = "СтандартныеПодсистемы.БазоваяФункциональность.ИдентификаторЗаполненияПараметровРаботыРасширений";
	ИдентификаторЗаполнения = СтандартныеПодсистемыСервер.ПараметрРаботыРасширения(ИмяПараметра, Истина);
	
	Возврат ПоследняяВерсияРасширений.ИдентификаторОбновления <> ИдентификаторЗаполнения;
	
КонецФункции

Функция ОбластьДанныхАктивноИспользуется()
	
	Сутки =  60*60*24;
	ИмяКонстанты = "ДатаПоследнегоСтартаКлиентскогоСеанса";
	МетаданныеКонстанты = Метаданные.Константы.Найти(ИмяКонстанты);
	Если МетаданныеКонстанты <> Неопределено Тогда
		Запрос = Новый Запрос;
		Запрос.УстановитьПараметр("ГраницаСтарта", ТекущаяУниверсальнаяДата() - Сутки*2);
		Запрос.Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ИСТИНА КАК ЗначениеИстина
		|ИЗ
		|	&Таблица КАК Таблица
		|ГДЕ
		|	Таблица.Значение >= &ГраницаСтарта";
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Таблица", МетаданныеКонстанты.ПолноеИмя());
		Если Не Запрос.Выполнить().Пустой() Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЕсли;
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("ГраницаАктивности",
		НачалоДня(ТекущаяДатаСеанса() - 60*60) - Сутки);
	Запрос.Текст =
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	ИСТИНА КАК ЗначениеИстина
	|ИЗ
	|	РегистрСведений.СведенияОПользователях КАК СведенияОПользователях
	|ГДЕ
	|	СведенияОПользователях.ДатаПоследнейАктивности >= &ГраницаАктивности";
	
	Возврат Не Запрос.Выполнить().Пустой();
	
КонецФункции

// Для процедур ПриПервомСерверномВызове, ПриУспешномНачалеВыполненияРегламентногоЗадания,
// общей формы Расширения и СтандартныеПодсистемыСервер.ПослеЗагрузкиДанных.
//
// Параметры:
//  Запустить - Булево
//  ВключитьБезусловно - Булево
//
Процедура ВключитьЗаполнениеПараметровРаботыРасширений(Запустить = Истина, ВключитьБезусловно = Ложь) Экспорт
	
	ИмяПараметра = "СтандартныеПодсистемы.БазоваяФункциональность.ИдентификаторЗаполненияПараметровРаботыРасширений";
	
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ПараметрыРаботыВерсийРасширений");
	ЭлементБлокировки.УстановитьЗначение("ВерсияРасширений", Справочники.ВерсииРасширений.ПустаяСсылка());
	ЭлементБлокировки.УстановитьЗначение("ИмяПараметра", ИмяПараметра);
	
	Отбор = Новый Структура("Метаданные", Метаданные.РегламентныеЗадания.ЗаполнениеПараметровРаботыРасширений);
	
	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		ИдентификаторОбновления = Справочники.ВерсииРасширений.ПоследняяВерсияРасширений().ИдентификаторОбновления;
		ИдентификаторЗаполнения = СтандартныеПодсистемыСервер.ПараметрРаботыРасширения(ИмяПараметра, Истина);
		Если ВключитьБезусловно Или ИдентификаторОбновления <> ИдентификаторЗаполнения Тогда
			Если ИдентификаторОбновления <> ИдентификаторЗаполнения Тогда
				СтандартныеПодсистемыСервер.УстановитьПараметрРаботыРасширения(ИмяПараметра,
					ИдентификаторОбновления, Истина);
			КонецЕсли;
			Задания = РегламентныеЗаданияСервер.НайтиЗадания(Отбор);
			Для Каждого Задание Из Задания Цикл
				РегламентныеЗаданияСервер.ИзменитьЗадание(Задание.УникальныйИдентификатор,
					Новый Структура("Использование", Истина));
			КонецЦикла;
		КонецЕсли;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
	Если Запустить Тогда
		ЗапуститьЗаполнениеПараметровРаботыРасширений(
			НСтр("ru = 'Запуск при включении заполнения параметров работы программы'"));
	КонецЕсли;
	
КонецПроцедуры

// Для процедуры ЗаполнитьВсеПараметрыРаботыПоследнейВерсииРасширений.
Процедура ЗаполнитьАктивноеФоновоеЗадание(ИсполняющееФоновоеЗадание, ИдентификаторЗадания)
	
	Если ТипЗнч(ИдентификаторЗадания) = Тип("УникальныйИдентификатор") Тогда
		ИсполняющееФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
		Если ИсполняющееФоновоеЗадание <> Неопределено
		   И ИсполняющееФоновоеЗадание.Состояние <> СостояниеФоновогоЗадания.Активно Тогда
			ИсполняющееФоновоеЗадание = Неопределено;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Для процедуры ЗаполнитьВсеПараметрыРаботыПоследнейВерсииРасширений
// и ОтметитьЗаполнениеПараметровРаботыРасширений.
//
// Параметры:
//  ВерсияПриЗапуске - см. Справочники.ВерсииРасширений.ПоследняяВерсияРасширений
//  Перезапустить    - Булево - возвращаемое значение.
//
Процедура ОтключитьЗаполнениеПараметровРаботыРасширений(ВерсияПриЗапуске, Перезапустить = Ложь)
	
	ИмяПараметра = "СтандартныеПодсистемы.БазоваяФункциональность.ИдентификаторЗаполненияПараметровРаботыРасширений";
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ПараметрыРаботыВерсийРасширений");
	ЭлементБлокировки.УстановитьЗначение("ВерсияРасширений", Справочники.ВерсииРасширений.ПустаяСсылка());
	ЭлементБлокировки.УстановитьЗначение("ИмяПараметра", ИмяПараметра);
	
	Отбор = Новый Структура("Метаданные", Метаданные.РегламентныеЗадания.ЗаполнениеПараметровРаботыРасширений);
	
	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		ТекущаяВерсия = Справочники.ВерсииРасширений.ПоследняяВерсияРасширений();
		
		Если ВерсияПриЗапуске.ВерсияРасширений = ТекущаяВерсия.ВерсияРасширений
		   И ВерсияПриЗапуске.ДатаОбновления = ТекущаяВерсия.ДатаОбновления
		   И Не КонфигурацияБазыДанныхИзмененаДинамически()
		   И Не Справочники.ВерсииРасширений.РасширенияИзмененыДинамически() Тогда
			
			ИдентификаторОбновления = ТекущаяВерсия.ИдентификаторОбновления;
			ИдентификаторЗаполнения = СтандартныеПодсистемыСервер.ПараметрРаботыРасширения(ИмяПараметра, Истина);
			Если ИдентификаторОбновления <> ИдентификаторЗаполнения Тогда
				СтандартныеПодсистемыСервер.УстановитьПараметрРаботыРасширения(ИмяПараметра,
					ИдентификаторОбновления, Истина);
			КонецЕсли;
			
			Задания = РегламентныеЗаданияСервер.НайтиЗадания(Отбор);
			Для Каждого Задание Из Задания Цикл
				РегламентныеЗаданияСервер.ИзменитьЗадание(Задание.УникальныйИдентификатор,
					Новый Структура("Использование", Ложь));
			КонецЦикла;
		Иначе
			Перезапустить = Истина;
		КонецЕсли;
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

// Для процедур ВключитьЗаполнениеПараметровРаботыРасширений,
// ЗаполнитьВсеПараметрыРаботыПоследнейВерсииРасширений и
// СтандартныеПодсистемыСервер.ПослеЗагрузкиДанных.
// 
// Параметры:
//  ОжидатьЗавершения - Булево - не учитывается для файловой ИБ.
//
Процедура ЗапуститьЗаполнениеПараметровРаботыРасширений(Комментарий, ОжидатьЗавершения = Ложь) Экспорт
	
	Если ТранзакцияАктивна()
	 Или МонопольныйРежим()
	   И Не ОжидатьЗавершения
	 Или КонфигурацияБазыДанныхИзмененаДинамически()
	   И ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда
		// В файловой ИБ перезапуск фонового задания с расширениями базы данных
		// выполняется с той же версией динамического поколения конфигурации.
		Возврат;
	КонецЕсли;
	
	ТекущийСеанс = ПолучитьТекущийСеансИнформационнойБазы();
	МетаданныеЗадания = Метаданные.РегламентныеЗадания.ЗаполнениеПараметровРаботыРасширений;
	
	НаименованиеЗадания =
		НСтр("ru = 'Автозапуск'", ОбщегоНазначения.КодОсновногоЯзыка())
		+ ": " + МетаданныеЗадания.Синоним + " ("
		+ СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'из сеанса %1 от %2'", ОбщегоНазначения.КодОсновногоЯзыка()),
			Формат(ТекущийСеанс.НомерСеанса, "ЧГ="),
			Формат(ТекущийСеанс.НачалоСеанса, "ДЛФ=DT")) + ")";
	
	ЗаписьЖурналаРегистрации(ИмяСобытияЗаполненияПараметров(),
		УровеньЖурналаРегистрации.Информация,,, Комментарий);
	
	ФоновоеЗадание = РасширенияКонфигурации.ВыполнитьФоновоеЗаданиеСРасширениямиБазыДанных(
		МетаданныеЗадания.ИмяМетода,,, НаименованиеЗадания);
	
	Если ОжидатьЗавершения
	   И ФоновоеЗадание <> Неопределено
	   И (ТекущийРежимЗапуска() <> Неопределено
	      Или Не ОбщегоНазначения.ИнформационнаяБазаФайловая()) Тогда
		
		ФоновоеЗадание.ОжидатьЗавершенияВыполнения();
	КонецЕсли;
	
КонецПроцедуры

// Для процедуры ЗаполнитьВсеПараметрыРаботыПоследнейВерсииРасширений.
Процедура ДобавитьДополнительныеСведения(Комментарий)
	
	ОписаниеРасширений = Справочники.ВерсииРасширений.ОписаниеРасширенийДляЖурнала();
	
	ДополнительныеСведения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = '*** Дополнительные сведения ***
		           |
		           |1. Подключенные расширения (включая исправления):
		           |%1
		           |
		           |2. Отключенные расширения (включая исправления):
		           |%2
		           |
		           |3. Все расширения базы данных (включая исправления):
		           |%3
		           |
		           |4. Версия расширений ""%4""
		           |%5'",
			ОбщегоНазначения.КодОсновногоЯзыка()),
		ОписаниеРасширений.Подключенные,
		ОписаниеРасширений.Отключенные,
		ОписаниеРасширений.Все,
		Строка(ПараметрыСеанса.ВерсияРасширений),
		ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ПараметрыСеанса.ВерсияРасширений, "ОписаниеМетаданных"));
	
	Комментарий = Комментарий + Символы.ПС + Символы.ПС + ДополнительныеСведения;
	
КонецПроцедуры

#Область ИнструментРазработчикаОбновлениеВспомогательныхДанных

// Возвращаемое значение:
//  Структура:
//   * Обновлять     - Булево - начальное значение Истина.
//   * ЕстьИзменения - Булево - начальное значение Ложь.
//
Функция НовыеСвойстваПараметраОбновления(Обновлять)
	
	НовыеСвойства = Новый Структура;
	НовыеСвойства.Вставить("Обновлять", Обновлять);
	НовыеСвойства.Вставить("ЕстьИзменения", Ложь);
	
	Возврат НовыеСвойства;
	
КонецФункции

#КонецОбласти

#КонецОбласти

#КонецЕсли